package lib

import (
	"encoding/json"
	"log"
	"net/http"

	"github.com/gorilla/websocket"
)

type Client struct {
	Conn *websocket.Conn
	Addr string
	Id   int
	Chan chan *MsgBody
}
type MsgBody struct {
	To   string `json:"to"`
	Type int    `json:"type"`
	Msg  string `json:"msg"`
	Err  string
}

const (
	//消息类型 1-list，2-广播，3-发给单用户
	MsgTypeList      = 1
	MsgTypeBroadcast = 2
	MsgTypeOne       = 3
)

var (
	ConnMap = make(map[string]*Client)
	count   = 0
)
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

//关闭连接，删除map中的addr
func (c *Client) closeConn() {
	c.Conn.Close()
	delete(ConnMap, c.Addr)
	log.Println("c.Conn.Close", c.Addr, ConnMap)
}

func (c *Client) handleMsg(msg *MsgBody) {

	switch {
	//给自己发用户列表
	case msg.Type == MsgTypeList:
		userList := make([]string, 0)
		for k, _ := range ConnMap {
			userList = append(userList, k)
		}
		j, _ := json.Marshal(userList)
		msg.Msg = string(j)
		break
	case msg.Type == MsgTypeBroadcast:
		break
	case msg.Type == MsgTypeOne:
		if _, ok := ConnMap[msg.To]; !ok {
			log.Println("用户不存在", msg.To)
			msg.To = c.Addr
			return
		}
		break

	}

}

func (c *Client) send(msg *MsgBody, r *ResBody) {
	switch {
	//给自己发用户列表
	case msg.Type == MsgTypeList:
		err1 := c.Conn.WriteMessage(websocket.TextMessage, []byte(r.ResMsg()))
		if err1 != nil {
			log.Println(err1)
		}
		break
	//发给所有人
	case msg.Type == MsgTypeBroadcast:
		for _, v := range ConnMap {
			err1 := v.Conn.WriteMessage(websocket.TextMessage, []byte(r.ResMsg()))
			if err1 != nil {
				log.Println(err1)
			}
		}
		break
	//发给指定用户
	case msg.Type == MsgTypeOne:
		err1 := ConnMap[msg.To].Conn.WriteMessage(websocket.TextMessage, []byte(r.ResMsg()))
		if err1 != nil {
			log.Println(err1)
		}
		break

	}
}

//写数据
func (c *Client) write() {
	defer func() {
		c.closeConn()
	}()
	for {
		msg := <-c.Chan
		// log.Println(c)
		res := &ResBody{}
		data := make(map[string]interface{})
		data["me"] = c.Addr
		if len(msg.Err) > 0 {
			res.Msg = msg.Err
			data["msg"] = ""
			data["type"] = msg.Type
			c.send(msg, res)

		} else {
			c.handleMsg(msg)
			data["msg"] = msg.Msg
			data["type"] = msg.Type
			res.Data = data
			c.send(msg, res)

		}

	}

}

//读数据
func (c *Client) read() {
	defer func() {
		c.closeConn()

	}()
	for {
		_, msg, err := c.Conn.ReadMessage()
		if err != nil {
			log.Println("c.Conn.ReadMessage", err)
			return
		}
		msgBody := MsgBody{}
		if err := json.Unmarshal(msg, &msgBody); err != nil {
			log.Println("json.Unmarshal(msg, &msgBody) err", err)
			msgBody := &MsgBody{To: c.Addr, Type: MsgTypeOne, Err: err.Error()}
			c.Chan <- msgBody
			continue
		}
		// log.Println("read", c.Addr, msgBody)

		c.Chan <- &msgBody

	}

}

//http升级为websocket
func ServerWs(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}
	addr := conn.RemoteAddr().String()
	log.Println("addr=", addr)
	count++
	ConnMap[addr] = &Client{Conn: conn, Addr: addr, Id: count, Chan: make(chan *MsgBody, 1)}
	c := ConnMap[addr]
	go c.write()
	go c.read()
}
